#pragma once

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>

class Util
{
public:
    //分隔符有很多，'\r\n'  '\n'  '\r'，我们统一按照'\n'的方式将各字段读取
    static int ReadLine(int sock, std::string &out) //读取报头信息，能够处理各种行分隔符
    {
        char ch = 'a'; //初始化，可以随便设置，只要不是\n就行，目的是为了进入循环
        while(ch != '\n') //如果行分隔符是'\n'，则自动退出循环，返回请求行长度
        {
            ssize_t s = recv(sock, &ch, 1, 0); //从sock里面读，读到ch里面，每次循环读1个字符
            if(s > 0) //读取成功
            {
                if(ch == '\r') //如果这个if条件成立，那么ch读取到的换行符有两种情况'\r\n' 和 '\r'
                {
                    //查看一下'\r'后面的内容，不取走
                    recv(sock, &ch, 1, MSG_PEEK); //MSG_PEEK这个选项，会直接返回接收队列的头部，但不取走，这叫做“数据窥探”
                    if(ch == '\n') recv(sock, &ch, 1, 0); //如果是'\r\n'，把'\r\n'转化成'\n'
                    else ch = '\n'; //如果就是一个'\r'则直接转化为'\n'
                }
                //走到这里后，只能有两种字符：普通字符和 '\n'
                out.push_back(ch);
            }
            else if(s == 0) return 0;//表面对方已经关闭连接，所有读到0
            else return -1;
        }
        return out.size();
    }

    static bool CutString(const std::string &target, std::string &sub1_out, std::string &sub2_out, std::string sep)
    {
        size_t pos = target.find(sep); //找到冒号的位置
        if(pos != std::string::npos)
        {
            sub1_out = target.substr(0, pos); //截取到冒号位置
            sub2_out = target.substr(pos+sep.size()); //分割符是"\n "，是一个\n加一个空格，所以截取后面位置要从pos+分隔符大小位置处开始
            return true;
        }
        return false;
    }
};